#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time    : 2021/2/26 21:56
# @Author  : cjw
from functools import wraps
from common.logs import log
import unittest


class DependencyError(Exception):

	def __init__(self, _type=0):
		self._type = _type

	def __str__(self):
		if self._type == 0:
			return f'Dependency name of test is required!'
		if self._type == 1:
			return f'Dependency name of test can not the case self!'


def depend(case=''):
	"""
	用例依赖装饰器
	适用范围：
	1、当前用例所依赖的用例必须先执行，装饰器才会起作用
	2、装饰器只对函数用例有效果
	:param case:
	:return:
	"""
	# 用例名称不能为空
	if not case:
		raise DependencyError
	# 记录用例的执行结果 失败的、错误的、跳过的
	_mark = []

	def wrap_fun(func):
		@wraps(func)
		def inner_func(self):
			# 用例名称不能是自己
			if case == func.__name__:
				raise DependencyError(_type=1)
			# 获取用例执行结果的属性
			_r = self._outcome.result
			# 元组列表 每个元组包含测试用例名称，失败/错误/跳过的原因
			_f, _e, _s = _r.failures, _r.errors, _r.skipped

			# 依赖的用例可以执行成功
			if not (_f or _e or _s):
				func(self)
			if _f:
				_mark.extend([fail[0] for fail in _f])  # 获取失败测试用例名称
			if _e:
				_mark.extend([error[0] for error in _e])  # 获取错误测试用例名称
			if _s:
				_mark.extend([skip[0] for skip in _s])  # 获取跳过测试用例名称

			# _mark 是函数列表，需要通过str函数转化为字符串函数名称列表
			# 跳过满足条件的用例，使用装饰器等价写法,条件不成立返回的函数本身，需要执行案例，条件成立则跳过
			unittest.skipIf(
				case in str(_mark),
				f'The pre-depend case: {case} has failed! Skip the specified case!'
			)(func)(self)

		return inner_func

	return wrap_fun


def logs(func):
	"""兼容日志装饰器"""

	@wraps(func)
	def wrap_func(*args, **kwargs):
		try:
			func(*args, **kwargs)
			log.info(f'{func.__name__}:{func.__doc__} 案例执行成功')
		except Exception:
			# 异常情况下，先进行截图, 然后打印日志
			args[0].imgs.append(args[0].driver.get_screenshot_as_base64())
			log.exception(f'{func.__name__}:{func.__doc__} 案例执行失败，步骤报错内容：')
			# 为了不影响案例执行的结果，需要抛出异常
			raise

	return wrap_func
